#ifndef		___MSG_STREAM__
#define		___MSG_STREAM__

#include "MsgBuffer.h"

#pragma warning(push)
#pragma warning(disable:4275)
#pragma warning(disable:4251)
#pragma warning(disable:4996)

//
//	Input stream for messages
//
class TCOM_API MsgIStream //: public std::basic_iostream<char>
{
public:
	MsgIStream(MsgBuffer& buffer);

	template<class ComplexType>
	MsgIStream& operator >> (ComplexType& val)
	{
		val.onDecode(*this);
		return *this;
	}

	template<>
	MsgIStream& operator >> (char& val);
	template<>
	MsgIStream& operator >> (unsigned char& val);

	template<>
	MsgIStream& operator >> (short& val);
	template<>
	MsgIStream& operator >> (unsigned short& val);

	template<>
	MsgIStream& operator >> (int& val);
	template<>
	MsgIStream& operator >> (unsigned int& val);

	template<>
	MsgIStream& operator >> (__int64& val);
	template<>
	MsgIStream& operator >> (unsigned __int64& val);

	template<>
	MsgIStream& operator >> (float& val);
	template<>
	MsgIStream& operator >> (string& val);

	
private:
	MsgBuffer&	m_theBuffer;
};

//
//	Output stream for messages
//
class TCOM_API MsgOStream //: public std::basic_ostream<char>
{
public:
	MsgOStream(MsgBuffer& buffer);
	template<class ComplexType>
	MsgOStream& operator << (const ComplexType& val)
	{
		val.onEncode(*this);
		return *this;
	}

	template<>
	MsgOStream& operator << (const char& val);
	template<>
	MsgOStream& operator << (const unsigned char& val);

	template<>
	MsgOStream& operator << (const short& val);
	template<>
	MsgOStream& operator << (const unsigned short& val);

	template<>
	MsgOStream& operator << (const int& val);
	template<>
	MsgOStream& operator << (const unsigned int& val);

	template<>
	MsgOStream& operator << (const __int64& val);
	template<>
	MsgOStream& operator << (const unsigned __int64& val);

	template<>
	MsgOStream& operator << (const float& val);
	template<>
	MsgOStream& operator << (const string& val);

private:
	MsgBuffer&	m_theBuffer;
};


template<>
MsgIStream& MsgIStream::operator >> (char& val)
{
	m_theBuffer.sgetn((char*)&val, sizeof(val));
	return *this;
}

template<>
MsgIStream& MsgIStream::operator >> (unsigned char& val)
{
	m_theBuffer.sgetn((char*)&val, sizeof(val));
	return *this;
}

template<>
MsgIStream& MsgIStream::operator >> (short& val)
{
	m_theBuffer.sgetn((char*)&val, sizeof(val));
	return *this;
}

template<>
MsgIStream& MsgIStream::operator >> (unsigned short& val)
{
	m_theBuffer.sgetn((char*)&val, sizeof(val));
	return *this;
}
template<>
MsgIStream& MsgIStream::operator >> (int& val)
{
	m_theBuffer.sgetn((char*)&val, sizeof(val));
	return *this;
}
template<>
MsgIStream& MsgIStream::operator >> (unsigned int& val)
{
	m_theBuffer.sgetn((char*)&val, sizeof(val));
	return *this;
}
template<>
MsgIStream& MsgIStream::operator >> (__int64& val)
{
	m_theBuffer.sgetn((char*)&val, sizeof(val));
	return *this;
}
template<>
MsgIStream& MsgIStream::operator >> (unsigned __int64& val)
{
	m_theBuffer.sgetn((char*)&val, sizeof(val));
	return *this;
}

template<>
MsgIStream& MsgIStream::operator >> (float& val)
{
	m_theBuffer.sgetn((char*)&val, sizeof(val));
	return *this;
}
template<>
MsgIStream& MsgIStream::operator >> (string& val)
{
	unsigned short size = 0;
	m_theBuffer.sgetn((char*)&size, sizeof(size));
	if (size!=0)
	{
		val.resize(size);
		m_theBuffer.sgetn((char*)val.data(), size);
	}
	return *this;
}


template<>
MsgOStream& MsgOStream::operator << (const char& val)
{
	m_theBuffer.sputc(val);
	return *this;
}
template<>
MsgOStream& MsgOStream::operator << (const unsigned char& val)
{
	m_theBuffer.sputc(val);
	return *this;
}
template<>
MsgOStream& MsgOStream::operator << (const short& val)
{
	m_theBuffer.sputn((char*)&val, sizeof(val));
	return *this;
}
template<>
MsgOStream& MsgOStream::operator << (const unsigned short& val)
{
	m_theBuffer.sputn((char*)&val, sizeof(val));
	return *this;
}
template<>
MsgOStream& MsgOStream::operator << (const int& val)
{
	m_theBuffer.sputn((char*)&val, sizeof(val));
	return *this;
}
template<>
MsgOStream& MsgOStream::operator << (const unsigned int& val)
{
	m_theBuffer.sputn((char*)&val, sizeof(val));
	return *this;
}
template<>
MsgOStream& MsgOStream::operator << (const __int64& val)
{
	m_theBuffer.sputn((char*)&val, sizeof(val));
	return *this;
}
template<>
MsgOStream& MsgOStream::operator << (const unsigned __int64& val)
{
	m_theBuffer.sputn((char*)&val, sizeof(val));
	return *this;
}

template<>
MsgOStream& MsgOStream::operator << (const float& val)
{
	m_theBuffer.sputn((char*)&val, sizeof(val));
	return *this;
}
template<>
MsgOStream& MsgOStream::operator << (const string& val)
{
	unsigned short size = val.size();
	m_theBuffer.sputn((char*)&size, sizeof(size));
	if (size!=0)
	{
		m_theBuffer.sputn(val.c_str(), size);
	}
	return *this;
}


#pragma warning(pop)
#endif